//
// Created by lwj12 on 24-8-13.
//
#include "string.h"
namespace lwj
{
    const size_t npos = -1;
    string::string(const char * str)
    : _size(strlen(str))
    {
        _capacity = _size;
        _str = new char[_size + 1];
        strcpy(_str, str);
    }

    string::string(const string& str)
    {
        string tmp(str._str);
        swap(tmp);
    }

    string::~string()
    {
        delete[] _str;
        _str = nullptr;
        _size = 0;
        _capacity = 0;
    }

    string& string::operator=(string tmp)
    {
        swap(tmp);
        return *this;
    }

    void string::insert(size_t pos, char ch)
    {
        assert(pos <= _size);
        if(_size == _capacity)
        {
            size_t newCapacity = _capacity == 0 ? 4 : 2 * _capacity;
            char* tmp = new char[newCapacity + 1];
            strcpy(tmp, _str);
            delete[] _str;
            _capacity = newCapacity;
            _str = tmp;
        }
        size_t end = _size + 1;
        while(end > pos)
        {
            _str[end] = _str[end - 1];
            end--;
        }
        _str[pos] = ch;
        _size++;
    }

    void string::insert(size_t pos, const string &s)
    {
        if(_capacity < _size + s._size)
        {
            char* tmp = new char[_size + s._size + 1];
            strcpy(tmp, _str);
            delete[] _str;
            _size += s._size;
            _capacity = _size;
            _str = tmp;
        }
        size_t end = _size - s._size + 1;
        while(end > pos)
        {
            _str[end + s._size - 1] = _str[end - 1];
            end--;
        }
        memcpy(_str + pos, s._str, s._size);
    }

    string& string::operator+=(char ch)
    {
        insert(_size, ch);
        return *this;
    }

    string& string::operator+=(const string &s)
    {
        insert(_size, s);
        return *this;
    }

    void string::reserve(size_t newCapacity)
    {
        if(newCapacity <= _capacity) return;
        char* tmp = new char[newCapacity + 1];
        strcpy(tmp, _str);
        delete[] _str;
        _str = tmp;
        _capacity = newCapacity;
    }

    void string::erase(size_t pos, size_t len)
    {
        assert(pos < _size);
        if(pos + len > _size - 1)
        {
            _str[pos] = '\0';
            _size = pos;
        }
        else
        {
            strcpy(_str + pos, _str + pos + len);
            _size -= len;
        }
    }

    size_t string::find(char ch, size_t pos) const
    {
        while(pos < _size) if(_str[pos++] == ch) return pos - 1;
        return -1;
    }

    size_t string::find(const char* str, size_t pos) const
    {
        char* p = strstr(_str, str);
        if(p == nullptr) return -1;
        return p - _str;
    }

    void string::swap(string& s)
    {
        std::swap(_str, s._str);
        std::swap(_size , s._size);
        std::swap(_capacity, s._capacity);
    }

    string string::substr(size_t pos, size_t len) const
    {
        // 确保 pos 在字符串的有效范围内
        assert(pos <= _size);
        // 如果 len 超过了从 pos 到末尾的长度，调整 len
        len = (pos + len > _size) ? (_size - pos) : len;
        string t;
        t.reserve(len);
        memcpy(t._str, _str + pos, len);
        t._str[len] = '\0';
        return t;
    }

    istream& operator>> (istream& in, string& str)
    {
        str.clear();
        char s[128];
        int i = 0;
        char ch = in.get();
        while (ch != '\n' && ch != ' ')
        {
            s[i++] = ch;
            if(i == 127)
            {
                s[i] = '\0';
                i = 0;
                str += s;
            }
            ch = in.get();
        }
        if(i != 0)
        {
            s[i] = '\0';
            str += s;
        }
        return in;
    }

    ostream& operator<< (ostream& out, const string& str)
    {
        out << str.c_str() << endl;
        return out;
    }

    bool string::operator<(const string& s) const
    {
        return strcmp(_str, s._str) < 0;
    }

    bool string::operator>(const string& s) const
    {
        return strcmp(_str, s._str) > 0;
    }

    bool string::operator<=(const string& s) const
    {
        return strcmp(_str, s._str) <= 0;
    }

    bool string::operator>=(const string& s) const
    {
        return strcmp(_str, s._str) >= 0;
    }

    bool string::operator==(const string& s) const
    {
        return strcmp(_str, s._str) == 0;
    }

    bool string::operator!=(const string& s) const
    {
        return !operator==(s);
    }
}
